/****************************************************
	文件：ABItem.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2020/9/27 11:27:16
	功能：AssetBundle数据项
*****************************************************/

using System;
using System.Collections.Generic;
using UnityEngine;
using HTUtility;

namespace HTFramework.ResKit
{
    public class ABItem : RefCounter
    {
        private ResRecorderType mRecorderType;
        private ResLoadState mLoadState;
        private bool mClearMemory;
        private Action<ABItem> OnLoadedEvent;
        private string mABName;

        public string ABName
        {
            get { return mABName; }
            set
            {
                if (value.Length != 0)
                {
                    mABName = value;
                    Path = ResUtil.GetABFullPath(value);
                }
            }
        }

        public uint Crc;

        public string Path;
        /// <summary>
        /// AssetBundle资源
        /// </summary>
        public AssetBundle AssetBundle;

        /// <summary>
        /// 缓存类型
        /// </summary>
        public ResRecorderType RecorderType
        {
            get => mRecorderType;
            set
            {
                if (mRecorderType != value)
                {
                    HTLogger.Debug("{0} 改变 RecorderType , \n{1} => {2}", ABName, mRecorderType.ToString(), value.ToString());
                    ResRecorder.Instance.RecordABItem(this, value);
                    mRecorderType = value;
                }
            }
        }
        /// <summary>
        /// 加载状态
        /// </summary>
        public ResLoadState LoadState
        {
            get => mLoadState;
            set
            {
                mLoadState = value;
                if (value == ResLoadState.LOADED)
                {
                    HTLogger.Warning("{0} 加载完成，开始执行完成回调", ABName);
                    OnLoadedEvent?.Invoke(this);
                    HTLogger.Warning("{0} 完成回调执行完毕，置空完成回调", ABName);
                    OnLoadedEvent = null;
                }
            }
        }
        /// <summary>
        /// 是否清除内存
        /// </summary>
        public bool ClearMemory
        {
            get => mClearMemory;
        }

        public ABItem() : base()
        {
            RecorderType = ResRecorderType.DEFAULT;
            LoadState = ResLoadState.UNLOADED;
            Crc = 0;
            Path = string.Empty;
            ABName = string.Empty;
            AssetBundle = null;
            OnLoadedEvent = null;
            mClearMemory = true;
        }
        /// <summary>
        /// RefCount ≤ 0时自动调用（外部无需手动调用）
        /// </summary>
        public override void OnDispose()
        {
            if (ClearMemory)
            {
                HTLogger.Debug("卸载AB包：{0}", ABName);
                RecorderType = ResRecorderType.UNLOADED;
                LoadState = ResLoadState.UNLOADED;
                if (AssetBundle != null)
                {
                    AssetBundle.Unload(true);
                }
                AssetBundle = null;
                OnLoadedEvent = null;
            }
            else
            {
                if (AssetBundle != null)
                {
                    RecorderType = ResRecorderType.IDLE;
                    LoadState = ResLoadState.LOADED;
                    OnLoadedEvent = null;
                }
            }
            mClearMemory = true;
        }
        /// <summary>
        /// 重置ResItem，便于对象池回收
        /// </summary>
        public void Reset()
        {
            Crc = 0;
            Path = string.Empty;
            ABName = string.Empty;
            RecorderType = ResRecorderType.DEFAULT;
            LoadState = ResLoadState.UNLOADED;
            AssetBundle = null;
            OnLoadedEvent = null;
            mClearMemory = true;
        }

        public void SubscribeLoadedEvent(Action<ABItem> onLoaded)
        {
            HTLogger.Debug("{0} 注册完成回调", ABName);
            OnLoadedEvent += onLoaded;
        }

        /// <summary>
        /// 同步加载
        /// </summary>
        public void DoLoadSync()
        {
            switch (LoadState)
            {
                case ResLoadState.UNLOADED:
                    HTLogger.Debug("（同步加载）{0} 开始同步加载", ABName);
                    break;
                case ResLoadState.LOADING:
                    HTLogger.Error("异步加载 AssetBundle 的同时不能进行同步加载，ABName：{0}", ABName);
                    return;
                case ResLoadState.LOADED:
                    HTLogger.Error("ABItem 的加载状态出错，ABName：{0}", ABName);
                    return;
            }

            LoadState = ResLoadState.LOADING;

            //加载AssetBundle
            AssetBundle = AssetBundle.LoadFromFile(Path);

            Retain();
            HTLogger.Debug("（同步加载）{0} 加载完成，引用计数+1，当前引用计数：{1}", ABName, mRefCount.Value);
            RecorderType = ResRecorderType.USING;
            LoadState = ResLoadState.LOADED;
        }
        /// <summary>
        /// 异步加载
        /// </summary>
        public void DoLoadAsync()
        {
            LoadState = ResLoadState.LOADING;

            HTLogger.Debug("（异步加载）{0} 开始异步加载", ABName);
            AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(Path);
            request.completed += asyncOperation =>
            {
                HTLogger.Debug("（异步加载）{0} 异步加载完毕", ABName);
                AssetBundle = request.assetBundle;

                Retain();
                HTLogger.Debug("（异步加载）{0} 加载完成，引用计数+1，当前引用计数：{1}", ABName, mRefCount.Value);
                RecorderType = ResRecorderType.USING;
                LoadState = ResLoadState.LOADED;
            };
        }
        /// <summary>
        /// 卸载AB资源
        /// </summary>
        public void DoRelease(bool clearMemory = true)
        {
            mClearMemory = clearMemory;
            //卸载自身
            Release();
            HTLogger.Debug("卸载AB包：{0}，当前引用：{1}", ABName, RefCount);
        }
    }
}
